package Test;


import static org.junit.Assert.assertTrue;

import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

import View.BuildingGUI;

import Dispatcher.*;
import HallCallStrategy.HallCallStrategy;
import HallCallStrategy.SmartHallCallStrategy;

public class DispatcherConcurrency {
	
	private static GroupDispatcher dispatcher;
	private static BuildingGUI gui;

	//create the group dispatcher
	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
		dispatcher = new GroupDispatcher();
		gui = new BuildingGUI(dispatcher);
		gui.setVisible(true);
		UpdateThread ut = new UpdateThread(dispatcher);
		ut.start();
	}

	@AfterClass
	public static void tearDownAfterClass() {
//		dispatcher.finalize();
	}
	
	//Tests if the server socket is bound to an address
	@Test
	public void testSocketActive(){
		assertTrue(dispatcher.serverSocket.isBound());
	}
	
	//Tests that the communications threads are created and started
	@Test
	public void testCommunicationThreadsActive(){
		assertTrue(dispatcher.commThreads.size()==10);
	}
	
	//Tests that communications threads are ready to communicate
	@Test
	public void testCommunicationsListening() {
		for(int i=0;i<dispatcher.commThreads.size();i++){
			assertTrue(dispatcher.commThreads.get(i).isAlive());
		}
	}
	
	@Test
	public void testRegisterElevators(){
		try {
			Thread.sleep(5000);
		} catch (InterruptedException e) {
			System.out.println("Thread Interrupted");
		}
		assertTrue(dispatcher.elevators.size() == 5);
	}
		
	@Test
	public void testReceiveUpdate(){
		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			System.out.println("Thread Interrupted");
		}
		assertTrue(dispatcher.status.size() == 5);
	}
	
	@Test
	public void testHallCall() throws InterruptedException{
		assertTrue(dispatcher.status.size() == 5);
		HallCallStrategy hc = new SmartHallCallStrategy();
		int bestElevatorIndex = hc.getBestElevator(10, 1,
				dispatcher.status);
		dispatcher.processHallCall(10, 1);
		Thread.sleep(1000);
		
		int bestElevatorIndex2 = hc.getBestElevator(5, -1,
				dispatcher.status);
		dispatcher.processHallCall(5, -1);
		Thread.sleep(1000);
		
		int bestElevatorIndex3 = hc.getBestElevator(4, 1,
				dispatcher.status);
		dispatcher.processHallCall(4, 1);
		Thread.sleep(1000);
		
		int bestElevatorIndex4 = hc.getBestElevator(3, -1,
				dispatcher.status);
		dispatcher.processHallCall(3, -1);
		Thread.sleep(1000);
		
		int bestElevatorIndex5 = hc.getBestElevator(7, 1,
				dispatcher.status);
		dispatcher.processHallCall(7, 1);

		Thread.sleep(1000);
		System.out.println(dispatcher.status.get(bestElevatorIndex).getNextDest());
		assertTrue(dispatcher.status.get(bestElevatorIndex).getNextDest() == 10);
		assertTrue(dispatcher.status.get(bestElevatorIndex2).getNextDest() == 5);
		assertTrue(dispatcher.status.get(bestElevatorIndex3).getNextDest() == 4);
		assertTrue(dispatcher.status.get(bestElevatorIndex4).getNextDest() == 3);
		assertTrue(dispatcher.status.get(bestElevatorIndex5).getNextDest() == 7);

		Thread.sleep(7000);
		while (dispatcher.status.get(bestElevatorIndex).getCurrentFloor() != 10) Thread.sleep(1);
		while (dispatcher.status.get(bestElevatorIndex2).getCurrentFloor() != 5) Thread.sleep(1);
		while (dispatcher.status.get(bestElevatorIndex3).getCurrentFloor() != 4) Thread.sleep(1);
		while (dispatcher.status.get(bestElevatorIndex4).getCurrentFloor() != 3) Thread.sleep(1);
		while (dispatcher.status.get(bestElevatorIndex5).getCurrentFloor() != 7) Thread.sleep(1);
		
		assertTrue(dispatcher.status.get(bestElevatorIndex).getCurrentFloor()==10);
		assertTrue(dispatcher.status.get(bestElevatorIndex2).getCurrentFloor()==5);
		assertTrue(dispatcher.status.get(bestElevatorIndex3).getCurrentFloor()==4);
		assertTrue(dispatcher.status.get(bestElevatorIndex4).getCurrentFloor()==3);
		assertTrue(dispatcher.status.get(bestElevatorIndex5).getCurrentFloor()==7);
	}
}
